package org.example.springboot.service;

import jakarta.annotation.Resource;
import org.example.springboot.DTO.ChartDataDTO;
import org.example.springboot.DTO.SystemStatsDTO;
import org.example.springboot.mapper.BookCategoryMapper;
import org.example.springboot.mapper.BookMapper;
import org.example.springboot.mapper.BorrowRecordMapper;
import org.example.springboot.mapper.UserMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 系统服务类
 */
@Service
public class SystemService {
    private static final Logger logger = LoggerFactory.getLogger(SystemService.class);

    @Resource
    private BookMapper bookMapper;
    
    @Resource
    private BookCategoryMapper bookCategoryMapper;
    
    @Resource
    private BorrowRecordMapper borrowRecordMapper;
    
    @Resource
    private UserMapper userMapper;
    
    /**
     * 获取系统统计数据
     * @return 统计数据DTO
     */
    public SystemStatsDTO getSystemStats() {
        logger.info("正在获取系统统计数据");
        
        // 查询图书总数
        Integer bookCount = Math.toIntExact(bookMapper.selectCount(null));
        logger.info("查询到图书总数：{}", bookCount);
        
        // 查询分类总数
        Integer categoryCount = Math.toIntExact(bookCategoryMapper.selectCount(null));
        logger.info("查询到分类总数：{}", categoryCount);
        
        // 查询借阅总数
        Integer borrowCount = Math.toIntExact(borrowRecordMapper.selectCount(null));
        logger.info("查询到借阅总数：{}", borrowCount);
        
        // 查询用户总数
        Integer userCount = Math.toIntExact(userMapper.selectCount(null));
        logger.info("查询到用户总数：{}", userCount);
        
        // 构建并返回统计数据
        return SystemStatsDTO.builder()
                .bookCount(bookCount)
                .categoryCount(categoryCount)
                .borrowCount(borrowCount)
                .userCount(userCount)
                .build();
    }
    
    /**
     * 获取图书分类分布数据
     * @return 分类分布数据
     */
    public List<ChartDataDTO.CategoryItem> getCategoryDistribution() {
        logger.info("正在获取图书分类分布数据");
        
        // 查询每个分类的图书数量
        List<Map<String, Object>> categoryData = bookMapper.selectCategoryDistribution();
        
        if (categoryData == null || categoryData.isEmpty()) {
            logger.warn("数据库中没有查询到分类分布数据，返回空列表");
            return Collections.emptyList();
        }
        
        logger.info("查询到{}个分类的图书分布数据", categoryData.size());
        
        // 转换数据格式
        List<ChartDataDTO.CategoryItem> result = categoryData.stream()
                .map(item -> {
                    String name = (String) item.get("categoryName");
                    Integer count = ((Number) item.get("bookCount")).intValue();
                    return new ChartDataDTO.CategoryItem(name, count);
                })
                .collect(Collectors.toList());
        
        logger.info("分类分布数据转换完成，共{}条记录", result.size());
        return result;
    }
    
    /**
     * 获取借阅趋势数据
     * @return 借阅趋势数据
     */
    public ChartDataDTO.BorrowTrendData getBorrowTrend() {
        logger.info("正在获取借阅趋势数据");
        
        // 获取最近12个月的月份列表
        List<String> months = getRecentMonths(12);
        logger.info("生成最近12个月的月份列表：{}", months);
        
        // 获取最近12个月的借阅和归还数据
        List<Map<String, Object>> borrowData = borrowRecordMapper.selectMonthlyBorrowData();
        List<Map<String, Object>> returnData = borrowRecordMapper.selectMonthlyReturnData();
        
        logger.info("查询到借阅数据：{} 条", borrowData != null ? borrowData.size() : 0);
        logger.info("查询到归还数据：{} 条", returnData != null ? returnData.size() : 0);
        
        // 构建借阅数据
        List<Integer> borrowCounts = new ArrayList<>();
        List<Integer> returnCounts = new ArrayList<>();
        
        // 填充借阅数据
        for (String month : months) {
            // 查找该月的借阅数据
            Optional<Map<String, Object>> borrowItem = (borrowData != null && !borrowData.isEmpty()) ?
                    borrowData.stream().filter(item -> month.equals(item.get("month"))).findFirst() :
                    Optional.empty();
            
            borrowCounts.add(borrowItem.map(item -> ((Number) item.get("count")).intValue()).orElse(0));
            
            // 查找该月的归还数据
            Optional<Map<String, Object>> returnItem = (returnData != null && !returnData.isEmpty()) ?
                    returnData.stream().filter(item -> month.equals(item.get("month"))).findFirst() :
                    Optional.empty();
            
            returnCounts.add(returnItem.map(item -> ((Number) item.get("count")).intValue()).orElse(0));
        }
        
        // 转换月份为更友好的格式
        List<String> formattedMonths = months.stream()
                .map(month -> month.substring(5) + "月")
                .collect(Collectors.toList());
        
        logger.info("借阅趋势数据构建完成");
        
        // 构建并返回数据
        return ChartDataDTO.BorrowTrendData.builder()
                .months(formattedMonths)
                .borrowData(borrowCounts)
                .returnData(returnCounts)
                .build();
    }
    
    /**
     * 获取用户活跃度数据
     * @return 用户活跃度数据
     */
    public List<ChartDataDTO.UserActivityItem> getUserActivity() {
        logger.info("正在获取用户活跃度数据");
        
        // 获取最近7天
        List<String> days = getRecentDays(7);
        logger.info("生成最近7天的日期列表：{}", days);
        
        // 查询最近7天的用户活跃度
        List<Map<String, Object>> activityData = userMapper.selectUserActivity();
        
        if (activityData == null || activityData.isEmpty()) {
            logger.warn("数据库中没有查询到用户活跃度数据，返回空列表");
            return Collections.emptyList();
        }
        
        logger.info("查询到用户活跃度数据：{} 条", activityData.size());
        
        // 构建结果列表
        List<ChartDataDTO.UserActivityItem> result = new ArrayList<>();
        
        // 星期几对应的中文
        String[] weekDays = {"周日", "周一", "周二", "周三", "周四", "周五", "周六"};
        
        // 填充数据
        for (String day : days) {
            // 查找该天的活跃数据
            Optional<Map<String, Object>> activityItem = activityData.stream()
                    .filter(item -> day.equals(item.get("day")))
                    .findFirst();
            
            // 获取星期几
            LocalDate date = LocalDate.parse(day);
            String weekDay = weekDays[date.getDayOfWeek().getValue() % 7];
            
            int userCount = activityItem.map(item -> ((Number) item.get("count")).intValue()).orElse(0);
            
            // 添加到结果
            result.add(new ChartDataDTO.UserActivityItem(weekDay, userCount));
            logger.debug("添加活跃度数据：{} - {} 人", weekDay, userCount);
        }
        
        logger.info("用户活跃度数据构建完成，共 {} 条记录", result.size());
        return result;
    }
    
    /**
     * 获取热门图书数据
     * @return 热门图书数据
     */
    public List<ChartDataDTO.HotBookItem> getHotBooks() {
        logger.info("正在获取热门图书数据");
        
        // 查询借阅次数最多的10本书
        List<Map<String, Object>> hotBooksData = bookMapper.selectHotBooks(10);
        
        if (hotBooksData == null || hotBooksData.isEmpty()) {
            logger.warn("数据库中没有查询到热门图书数据，返回空列表");
            return Collections.emptyList();
        }
        
        logger.info("查询到热门图书数据：{} 条", hotBooksData.size());
        
        // 转换数据格式
        List<ChartDataDTO.HotBookItem> result = hotBooksData.stream()
                .map(item -> {
                    String name = (String) item.get("title");
                    Integer count = ((Number) item.get("borrowCount")).intValue();
                    return new ChartDataDTO.HotBookItem(name, count);
                })
                .collect(Collectors.toList());
        
        logger.info("热门图书数据转换完成，共 {} 条记录", result.size());
        return result;
    }
    
    /**
     * 获取高分图书数据
     * @return 高分图书数据
     */
    public List<ChartDataDTO.TopRatedBookItem> getTopRatedBooks() {
        logger.info("正在获取高分图书数据");
        
        // 查询评分最高的10本书
        List<Map<String, Object>> topRatedBooksData = bookMapper.selectTopRatedBooks(10);
        
        if (topRatedBooksData == null || topRatedBooksData.isEmpty()) {
            logger.warn("数据库中没有查询到高分图书数据，返回空列表");
            return Collections.emptyList();
        }
        
        logger.info("查询到高分图书数据：{} 条", topRatedBooksData.size());
        
        // 转换数据格式
        List<ChartDataDTO.TopRatedBookItem> result = topRatedBooksData.stream()
                .map(item -> {
                    String name = (String) item.get("title");
                    Double rating;
                    Object ratingObj = item.get("rating");
                    
                    // 处理不同类型的评分值
                    if (ratingObj instanceof Number) {
                        rating = ((Number) ratingObj).doubleValue();
                    } else {
                        // 如果评分不是数字，设置为0
                        rating = 0.0;
                        logger.warn("图书 {} 的评分不是数字类型", name);
                    }
                    
                    return new ChartDataDTO.TopRatedBookItem(name, rating);
                })
                .collect(Collectors.toList());
        
        logger.info("高分图书数据转换完成，共 {} 条记录", result.size());
        return result;
    }
    
    /**
     * 获取最近n个月份
     * @param n 月份数
     * @return 月份列表，格式yyyy-MM
     */
    private List<String> getRecentMonths(int n) {
        List<String> months = new ArrayList<>();
        LocalDate date = LocalDate.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");
        
        // 添加当前月份
        months.add(date.format(formatter));
        
        // 添加前n-1个月
        for (int i = 1; i < n; i++) {
            date = date.minusMonths(1);
            months.add(0, date.format(formatter));
        }
        
        return months;
    }
    
    /**
     * 获取最近n天
     * @param n 天数
     * @return 日期列表，格式yyyy-MM-dd
     */
    private List<String> getRecentDays(int n) {
        List<String> days = new ArrayList<>();
        LocalDate date = LocalDate.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        
        // 添加当前日期
        days.add(date.format(formatter));
        
        // 添加前n-1天
        for (int i = 1; i < n; i++) {
            date = date.minusDays(1);
            days.add(0, date.format(formatter));
        }
        
        return days;
    }
} 